﻿using JESAI.Core.Websocket.Client.Exceptions;
using JESAI.Core.Websocket.Client.Messages;
using JESAI.Core.Websocket.Client.Models;
using JESAI.Core.Websocket.Client.Threading;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.IO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.WebSockets;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace JESAI.Core.Websocket.Client
{
    public partial class WebsocketClient : IWebsocketClient
    {
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<WebsocketClient> _logger;

        /// <summary>
        /// 异步锁
        /// </summary>
        private readonly AsyncLock _locker = new AsyncLock();

        /// <summary>
        /// 连接工厂
        /// </summary>
        private readonly Func<Uri, CancellationToken, Task<WebSocket>> _connectionFactory;

        /// <summary>
        /// 可回收内存流管理器
        /// </summary>
        private readonly RecyclableMemoryStreamManager? _memoryStreamManager;

        /// <summary>
        /// 懒惰的全局可回收内存流管理器实例
        /// </summary>
        private static readonly Lazy<RecyclableMemoryStreamManager> _globalMemoryStreamManager = new Lazy<RecyclableMemoryStreamManager>(new RecyclableMemoryStreamManager());

        /// <summary>
        /// 获取当前使用的可回收内存流管理器实例
        /// </summary>
        private RecyclableMemoryStreamManager MemoryStreamManager =>
         _memoryStreamManager ?? _globalMemoryStreamManager.Value;

        /// <summary>
        /// WebSocket客户端地址
        /// </summary>
        private Uri _url;

        /// <summary>
        /// 检查最后接收消息的定时器
        /// </summary>
        private Timer? _lastChanceTimer;

        /// <summary>
        /// 最后一次接收到消息的时间
        /// </summary>
        private DateTime _lastReceivedMsg = DateTime.UtcNow;

        private Timer? _errorReconnectTimer;

        /// <summary>
        /// 是否正在销毁
        /// </summary>
        private bool _disposing;

        /// <summary>
        /// 是否正在重连
        /// </summary>
        private bool _reconnecting;

        /// <summary>
        /// 是否正在停止
        /// </summary>
        private bool _stopping;

        /// <summary>
        /// 是否启用重连
        /// </summary>
        private bool _isReconnectionEnabled = true;

        /// <summary>
        /// WebSocket客户端
        /// </summary>
        private WebSocket? _client;

        /// <summary>
        /// 
        /// </summary>
        private CancellationTokenSource? _cancellation;

        /// <summary>
        /// 
        /// </summary>
        private CancellationTokenSource? _cancellationTotal;

        private readonly Subject<ResponseMessage> _messageReceivedSubject = new Subject<ResponseMessage>();
        private readonly Subject<ReconnectionInfo> _reconnectionSubject = new Subject<ReconnectionInfo>();
        private readonly Subject<DisconnectionInfo> _disconnectedSubject = new Subject<DisconnectionInfo>();

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="url">目标websocket url (wss://)</param>
        /// <param name="clientFactory">原生ClientWebSocket的可选工厂，需要一些自定义功能（代理、设置等）时使用它</param>
        /// <param name="memoryStreamManager">可选的内存流管理器，可在多种场合重复使用</param>
        public WebsocketClient(Uri url, Func<ClientWebSocket>? clientFactory = null, RecyclableMemoryStreamManager? memoryStreamManager = null)
            : this(url, null, GetClientFactory(clientFactory), memoryStreamManager)
        {
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="url">目标websocket url(wss://)</param>
        /// <param name="logger">记录器实例，可以为空</param>
        /// <param name="clientFactory">原生ClientWebSocket的可选工厂，需要一些自定义功能（代理、设置等）时使用它</param>
        /// <param name="memoryStreamManager">可选的内存流管理器，可在多种场合重复使用</param>
        public WebsocketClient(Uri url, ILogger<WebsocketClient>? logger, Func<ClientWebSocket>? clientFactory = null, RecyclableMemoryStreamManager? memoryStreamManager = null)
            : this(url, logger, GetClientFactory(clientFactory), memoryStreamManager)
        {
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="url">目标websocket url(wss://)</param>
        /// <param name="logger">记录器实例，可以为空</param>
        /// <param name="connectionFactory">可选工厂，用于本地创建和连接到websocket。该方法应返回一个已连接的 <see cref="WebSocket"/>。无论何时需要一些自定义功能（代理、设置等），都可以使用它</param>
        /// <param name="memoryStreamManager">可选的内存流管理器，可在多种场合重复使用</param>
        public WebsocketClient(Uri url, ILogger<WebsocketClient>? logger, Func<Uri, CancellationToken, Task<WebSocket>>? connectionFactory, RecyclableMemoryStreamManager? memoryStreamManager = null)
        {
            Validations.Validations.ValidateInput(url, nameof(url));

            _logger = logger ?? NullLogger<WebsocketClient>.Instance;
            _url = url;
            _connectionFactory = connectionFactory ?? (async (uri, token) =>
            {
                //var client = new ClientWebSocket
                //{
                //    Options = { KeepAliveInterval = new TimeSpan(0, 0, 5, 0) }
                //};
                var client = new ClientWebSocket();
                await client.ConnectAsync(uri, token).ConfigureAwait(false);
                return client;
            });
            _memoryStreamManager = memoryStreamManager;
        }

        /// <summary>
        /// 远程服务器地址。更改后重新连接。
        /// </summary>
        public Uri Url
        {
            get => _url;
            set
            {
                Validations.Validations.ValidateInput(value, nameof(Url));
                _url = value;
            }
        }

        /// <summary>
        /// 接收到的消息流（原始格式），订阅消息
        /// </summary>
        public IObservable<ResponseMessage> MessageReceived => _messageReceivedSubject.AsObservable();

        /// <summary>
        /// 重新连接事件流（在新连接后触发）
        /// </summary>
        public IObservable<ReconnectionInfo> ReconnectionHappened => _reconnectionSubject.AsObservable();

        /// <summary>
        /// 断开连接事件流（在连接丢失后触发）
        /// </summary>
        public IObservable<DisconnectionInfo> DisconnectionHappened => _disconnectedSubject.AsObservable();

        /// <summary>
        /// 如果没有来自服务器的消息，在重新连接之前等待多长时间的时间范围。
        /// 设置null可禁用此功能。
        /// 默认值：1分钟
        /// </summary>
        public TimeSpan? ReconnectTimeout { get; set; } = TimeSpan.FromMinutes(1);

        /// <summary>
        /// 如果上次重新连接失败，在重新连接之前等待多长时间的时间范围。
        /// 设置null可禁用此功能。
        /// 默认值：1分钟
        /// </summary>
        public TimeSpan? ErrorReconnectTimeout { get; set; } = TimeSpan.FromMinutes(1);

        /// <summary>
        /// 如果连接因瞬态错误而丢失，在重新连接之前等待多长时间的时间范围。
        /// 设置null可禁用此功能。
        /// 默认值：空/禁用（立即）
        /// </summary>
        public TimeSpan? LostReconnectTimeout { get; set; }

        /// <summary>
        /// 启用或禁用重新连接功能（默认启用）
        /// </summary>
        public bool IsReconnectionEnabled
        {
            get => _isReconnectionEnabled;
            set
            {
                _isReconnectionEnabled = value;

                if (IsStarted)
                {
                    if (_isReconnectionEnabled)
                    {
                        ActivateLastChance();
                    }
                    else
                    {
                        DeactivateLastChance();
                    }
                }
            }
        }

        /// <summary>
        /// 获取或设置当前websocket客户端实例的名称。
        /// 用于日志记录目的（以防您使用更多并行websocket客户端并希望区分它们）
        /// </summary>
        public string? Name { get; set; }

        /// <summary>
        ///  如果Start（）方法至少被调用过一次，则返回true。如果未启动或处理，则为False
        /// </summary>
        public bool IsStarted { get; private set; }

        /// <summary>
        /// 如果客户端正在运行并连接到服务器，则返回true
        /// </summary>
        public bool IsRunning { get; private set; }

        /// <summary>
        /// 启用或禁用从二进制到字符串的文本消息转换（通过“MessageEncoding”属性）。
        /// 默认值：true
        /// </summary>
        public bool IsTextMessageConversionEnabled { get; set; } = true;

        /// <summary>
        /// 启用或禁用自动 <see cref="MemoryStream.Dispose(bool)"/> 的 <see cref="MemoryStream"/> 
        /// 发送数据后（仅适用于二进制响应）。
        /// 将值设置为false允许您直接访问流。
        /// <warning>但是，请记住，您需要自己处理处置。</warning>
        /// 默认值：true
        /// </summary>
        public bool IsStreamDisposedAutomatically { get; set; } = true;

        /// <summary>
        /// 文本消息的目标编码
        /// </summary>
        public Encoding? MessageEncoding { get; set; }

        /// <summary>
        /// 基础客户端，每次重新连接后都会发生变化，请谨慎使用
        /// </summary>
        public ClientWebSocket? NativeClient => GetSpecificOrThrow(_client);

        /// <summary>
        /// 终止websocket连接并清理所有内容
        /// </summary>
        public void Dispose()
        {
            _disposing = true;
            _logger.LogDebug(L("WebSocket客户端销毁中.."), Name);
            try
            {
                _messagesTextToSendQueue.Writer.Complete();
                _messagesBinaryToSendQueue.Writer.Complete();
                _lastChanceTimer?.Dispose();
                _errorReconnectTimer?.Dispose();
                _cancellation?.Cancel();
                _cancellationTotal?.Cancel();
                _client?.Abort();
                _client?.Dispose();
                _cancellation?.Dispose();
                _cancellationTotal?.Dispose();
                _messageReceivedSubject.OnCompleted();
                _reconnectionSubject.OnCompleted();
            }
            catch (Exception e)
            {
                _logger.LogError(e, L("处置客户端失败，错误: {error}"), Name, e.Message);
            }

            if (IsRunning)
            {
                _disconnectedSubject.OnNext(DisconnectionInfo.Create(DisconnectionType.Exit, _client, null));
            }

            IsRunning = false;
            IsStarted = false;
            _disconnectedSubject.OnCompleted();
        }

        /// <summary>
        /// 开始在后台线程上监听websocket流。
        /// 如果发生连接错误，它不会抛出异常。
        /// 仅通过“DisconnectionHappened”流式传输消息并记录。
        /// </summary>
        public Task Start()
        {
            return StartInternal(false);
        }

        /// <summary>
        /// 开始在后台线程上监听websocket流。
        /// 如果发生连接错误，它不会抛出异常。
        /// 仅通过“DisconnectionHappened”流式传输消息并记录。
        /// </summary>
        /// <param name="startBackgroundThreadSendText"></param>
        /// <param name="startBackgroundThreadSendBinary"></param>
        /// <returns></returns>
        public Task Start(bool startBackgroundThreadSendText = true, bool startBackgroundThreadSendBinary = false)
        {
            return StartInternal(false);
        }

        /// <summary>
        /// 开始在后台线程上监听websocket流。
        /// 如果发生连接错误，它会抛出异常。
        /// 快速失败的方法。 
        /// </summary>
        public Task StartOrFail()
        {
            return StartInternal(true);
        }

        /// <summary>
        /// 开始在后台线程上监听websocket流。
        /// 如果发生连接错误，它会抛出异常。
        /// 快速失败的方法。 
        /// </summary>
        /// <param name="startBackgroundThreadSendText"> 是否启动后台线程发送文本消息 </param>
        /// <param name="startBackgroundThreadSendBinary"> 是否启动后台线程发送二进制消息 </param>
        /// <returns></returns>
        public Task StartOrFail(bool startBackgroundThreadSendText = true, bool startBackgroundThreadSendBinary = false)
        {
            return StartInternal(true);
        }
        /// <summary>
        /// 使用自定义关闭代码停止/关闭websocket连接。
        /// 方法不抛出异常，只记录异常并将客户端标记为关闭。 
        /// </summary>
        /// <returns>如果关闭成功启动，则返回true</returns>
        public async Task<bool> Stop(WebSocketCloseStatus status, string statusDescription)
        {
            var result = await StopInternal(
                _client,
                status,
                statusDescription,
                null,
                false,
                false).ConfigureAwait(false);
            _disconnectedSubject.OnNext(DisconnectionInfo.Create(DisconnectionType.ByUser, _client, null));
            return result;
        }

        /// <summary>
        /// 使用自定义关闭代码停止/关闭websocket连接。
        /// 方法可能会抛出异常，但客户端仍被标记为关闭。
        /// </summary>
        /// <returns>如果关闭成功启动，则返回true</returns>
        public async Task<bool> StopOrFail(WebSocketCloseStatus status, string statusDescription)
        {
            var result = await StopInternal(
                _client,
                status,
                statusDescription,
                null,
                true,
                false).ConfigureAwait(false);
            _disconnectedSubject.OnNext(DisconnectionInfo.Create(DisconnectionType.ByUser, _client, null));
            return result;
        }

        /// <summary>
        /// 获取客户端工厂函数
        /// </summary>
        /// <param name="clientFactory"></param>
        /// <returns></returns>
        private static Func<Uri, CancellationToken, Task<WebSocket>>? GetClientFactory(Func<ClientWebSocket>? clientFactory)
        {
            if (clientFactory == null)
                return null;

            return (async (uri, token) =>
            {
                var client = clientFactory();
                await client.ConnectAsync(uri, token).ConfigureAwait(false);
                return client;
            });
        }

        /// <summary>
        /// 内部开始方法
        /// </summary>
        /// <param name="failFast">是否快速失败，快速失败则抛出异常，否则重试</param>
        /// <returns></returns>
        /// <exception cref="WebsocketException"></exception>
        private async Task StartInternal(bool failFast, bool startBackgroundThreadSendText = true, bool startBackgroundThreadSendBinary = false, bool openHeartBeat = true)
        {
            if (_disposing)
            {
                throw new WebsocketException($"客户端 {Name} 已经被销毁,不允许启动!");
            }

            if (IsStarted)
            {
                _logger.LogDebug(L("客户端已经启动, 忽略.."), Name);
                return;
            }

            IsStarted = true;

            _logger.LogDebug(L("WebSocket客户端启动中.."), Name);
            _cancellation = new CancellationTokenSource();
            _cancellationTotal = new CancellationTokenSource();

            await StartClient(_url, _cancellation.Token, ReconnectionType.Initial, failFast).ConfigureAwait(false);

            //开启一个发送文本队列的后台线程
            if (startBackgroundThreadSendText)
                StartBackgroundThreadForSendingText();
            //开启一个发送二进制队列的后台线程
            if (startBackgroundThreadSendBinary)
                StartBackgroundThreadForSendingBinary();

            if (openHeartBeat)
                StartBackgroundThreadForHeartBeat();
        }

        /// <summary>
        /// 停止客户端的内部方法
        /// </summary>
        /// <param name="client"></param>
        /// <param name="status"></param>
        /// <param name="statusDescription"></param>
        /// <param name="cancellation"></param>
        /// <param name="failFast"></param>
        /// <param name="byServer"></param>
        /// <returns></returns>
        /// <exception cref="WebsocketException"></exception>
        private async Task<bool> StopInternal(WebSocket? client, WebSocketCloseStatus status, string statusDescription,
            CancellationToken? cancellation, bool failFast, bool byServer)
        {
            if (_disposing)
            {
                throw new WebsocketException($"WebSocket客户端 {Name} 已经被销毁, 不允许停止!");
            }

            DeactivateLastChance();

            if (client == null)
            {
                IsStarted = false;
                IsRunning = false;
                return false;
            }

            if (!IsRunning)
            {
                _logger.LogInformation(L("WebSocket客户端已经停止"), Name);
                IsStarted = false;
                return false;
            }

            var result = false;
            try
            {
                var cancellationToken = cancellation ?? CancellationToken.None;
                _stopping = true;
                if (byServer)
                    await client.CloseOutputAsync(status, statusDescription, cancellationToken);
                else
                    await client.CloseAsync(status, statusDescription, cancellationToken);
                result = true;
            }
            catch (Exception e)
            {
                _logger.LogError(e, L("停止客户端时出错，消息: '{error}'"), Name, e.Message);

                if (failFast)
                {
                    // 快速失败，抛出异常
                    throw new WebsocketException($"未能停止Websocket客户端 {Name}, 错误: '{e.Message}'", e);
                }
            }
            finally
            {
                IsRunning = false;
                _stopping = false;

                if (!byServer || !IsReconnectionEnabled)
                {
                    // 手动停止或未重新连接，将客户端标记为未启动
                    IsStarted = false;
                }
            }

            return result;
        }

        /// <summary>
        /// 启动客户端
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="token">取消客户端的令牌</param>
        /// <param name="type"></param>
        /// <param name="failFast"></param>
        /// <returns></returns>
        /// <exception cref="WebsocketException"></exception>
        private async Task StartClient(Uri uri, CancellationToken token, ReconnectionType type, bool failFast)
        {
            //要先停止检查最后接收消息的定时器
            DeactivateLastChance();

            try
            {
                //创建客户端
                _client = await _connectionFactory(uri, token).ConfigureAwait(false);
                //监听接收消息
                _ = Listen(_client, token);
                //设置状态
                IsRunning = true;
                IsStarted = true;
                //发布重新连接事件
                _reconnectionSubject.OnNext(ReconnectionInfo.Create(type));
                //更新最后接收消息时间
                _lastReceivedMsg = DateTime.UtcNow;
                //激活最后接收消息的定时器
                ActivateLastChance();
            }
            catch (Exception e)
            {
                var info = DisconnectionInfo.Create(DisconnectionType.Error, _client, e);
                _disconnectedSubject.OnNext(info);

                if (info.CancelReconnection)
                {
                    // 用户取消重新连接，不执行任何操作
                    _logger.LogError(e, L("连接时出现异常。用户取消重新连接，退出。错误： '{error}'"), Name, e.Message);
                    return;
                }

                if (failFast)
                {
                    // 快速失败，传播异常
                    // 不要重新连接
                    throw new WebsocketException($"启动Websocket客户端失败 {Name}, 错误: '{e.Message}'", e);
                }

                if (ErrorReconnectTimeout == null)
                {
                    _logger.LogError(e, L("连接时出现异常。重新连接已禁用，退出。错误： '{error}'"), Name, e.Message);
                    return;
                }

                var timeout = ErrorReconnectTimeout.Value;
                _logger.LogError(e, L("连接时出现异常。在下次重新连接尝试之前等待{timeout}秒。错误：'{error}'"), Name, timeout.TotalSeconds, e.Message);
                _errorReconnectTimer?.Dispose();
                _errorReconnectTimer = new Timer(ReconnectOnError, e, timeout, Timeout.InfiniteTimeSpan);
            }
        }

        private void ReconnectOnError(object? state)
        {
            // await Task.Delay(timeout, token).ConfigureAwait(false);
            _ = Reconnect(ReconnectionType.Error, false, state as Exception).ConfigureAwait(false);
        }

        /// <summary>
        /// 客户端是否已经连接
        /// </summary>
        /// <returns></returns>
        private bool IsClientConnected()
        {
            return _client?.State == WebSocketState.Open;
        }

        /// <summary>
        /// 监听消息
        /// </summary>
        /// <param name="client"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        private async Task Listen(WebSocket client, CancellationToken token)
        {
            Exception? causedException = null;
            try
            {
                // 在此处定义缓冲区并重用，以避免更多的分配
                const int chunkSize = 1024 * 4;
                var buffer = new Memory<byte>(new byte[chunkSize]);

                do
                {
                    ValueWebSocketReceiveResult result;
                    var ms = MemoryStreamManager.GetStream();

                    while (true)
                    {
                        result = await client.ReceiveAsync(buffer, token);
                        ms.Write(buffer[..result.Count].Span);

                        if (result.EndOfMessage)
                            break;
                    }

                    ms.Seek(0, SeekOrigin.Begin);

                    ResponseMessage message;
                    bool shouldDisposeStream = true;

                    if (result.MessageType == WebSocketMessageType.Text && IsTextMessageConversionEnabled)
                    {
                        var data = GetEncoding().GetString(ms.GetBuffer(), 0, (int)ms.Length);
                        message = ResponseMessage.TextMessage(data);
                    }
                    else if (result.MessageType == WebSocketMessageType.Close)
                    {
                        _logger.LogTrace(L("收到关闭消息"), Name);

                        if (!IsStarted || _stopping)
                        {
                            return;
                        }

                        var info = DisconnectionInfo.Create(DisconnectionType.ByServer, client, null);
                        _disconnectedSubject.OnNext(info);

                        if (info.CancelClosing)
                        {
                            // 关闭已取消，如果已启用，请重新连接
                            if (IsReconnectionEnabled)
                            {
                                throw new OperationCanceledException($"Websocket连接已被服务器关闭 (客户端名称: {Name})");
                            }

                            continue;
                        }

                        await StopInternal(client, WebSocketCloseStatus.NormalClosure, "Closing",
                            token, false, true);

                        // 如果已启用，请重新连接
                        if (IsReconnectionEnabled && !ShouldIgnoreReconnection(client))
                        {
                            _ = ReconnectSynchronized(ReconnectionType.Lost, false, null);
                        }

                        return;
                    }
                    else
                    {
                        if (IsStreamDisposedAutomatically)
                        {
                            message = ResponseMessage.BinaryMessage(ms.ToArray());
                        }
                        else
                        {
                            message = ResponseMessage.BinaryStreamMessage(ms);
                            shouldDisposeStream = false;
                        }
                    }

                    if (shouldDisposeStream)
                        ms.Dispose();

                    _logger.LogTrace(L("接收消息:  {message}"), Name, message);
                    //更新最后接收消息时间
                    _lastReceivedMsg = DateTime.UtcNow;
                    //发布消息
                    _messageReceivedSubject.OnNext(message);

                } while (client.State == WebSocketState.Open && !token.IsCancellationRequested);
            }
            catch (TaskCanceledException e)
            {
                // 任务已取消，忽略
                causedException = e;
            }
            catch (OperationCanceledException e)
            {
                // 操作已取消，忽略
                causedException = e;
            }
            catch (ObjectDisposedException e)
            {
                // 客户端已处理，忽略
                causedException = e;
            }
            catch (Exception e)
            {
                _logger.LogError(e, L("监听websocket流时出错，错误： '{error}'"), Name, e.Message);
                causedException = e;
            }

            if (ShouldIgnoreReconnection(client) || !IsStarted)
            {
                //重新连接已在进行中或客户端已停止/处理，什么都不做
                return;
            }

            if (LostReconnectTimeout.HasValue)
            {
                var timeout = LostReconnectTimeout.Value;
                _logger.LogWarning(L("侦听websocket流丢失。在下次重新连接尝试之前等待{timeout}秒。"), Name, timeout.TotalSeconds);
                await Task.Delay(timeout, token).ConfigureAwait(false);
            }

            // 监听线程丢失，必须重新连接
            _ = ReconnectSynchronized(ReconnectionType.Lost, false, causedException);
        }

        private bool ShouldIgnoreReconnection(WebSocket client)
        {
            // 重新连接已在进行中或客户端已停止/处理，
            var inProgress = _disposing || _reconnecting || _stopping;

            // 已重新连接
            var differentClient = client != _client;

            return inProgress || differentClient;
        }

        /// <summary>
        /// 获取当前的编码
        /// </summary>
        /// <returns></returns>
        private Encoding GetEncoding()
        {
            if (MessageEncoding == null)
                MessageEncoding = Encoding.UTF8;
            return MessageEncoding;
        }

        /// <summary>
        /// 获取ClientWebSocket特定客户端
        /// </summary>
        /// <param name="client"></param>
        /// <returns></returns>
        /// <exception cref="WebsocketException"></exception>
        private ClientWebSocket? GetSpecificOrThrow(WebSocket? client)
        {
            if (client == null)
                return null;
            var specific = client as ClientWebSocket;
            if (specific == null)
                throw new WebsocketException("无法将“WebSocket”客户端转换为“ClientWebSocket”，请通过工厂提供正确的类型，或者根本不使用此属性。");
            return specific;
        }

        /// <summary>
        /// 格式化
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        private string L(string msg)
        {
            return $"[WEBSOCKET {{name}}] {msg}";
        }

        /// <summary>
        /// 重连类型转换为断开连接类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private DisconnectionType TranslateTypeToDisconnection(ReconnectionType type)
        {
            // 注意枚举索引必须相互对应
            return (DisconnectionType)type;
        }
    }
}
